package edu.polsl.bio.str.common.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

/**
 * //todo class description
 * <p/>
 * Created on: Jun 14, 2011 5:59:13 PM <br/>
 * <a href="http://www.polsl.pl">www.polsl.pl</a>
 *
 * @author lukasz.olczak@polsl.pl
 */
public class SerializationUtils {
  /**
   * slf4j Logger.
   */
  private static final Logger log = LoggerFactory.getLogger(SerializationUtils.class.getName());

  public static void saveAndCompressObject(Object obj, File file) {
    ObjectOutputStream out = null;
    // Serialize to a byte array
    try {
      FileOutputStream fOut = new FileOutputStream(file);
      OutputStream rOut = new BufferedOutputStream(new GZIPOutputStream(fOut));
      out = new ObjectOutputStream(rOut);
      out.writeObject(obj);
      out.flush();
    } catch (IOException e) {
      throw new RuntimeException(e);
    } finally {
      if (out != null) {
        try {
          out.close();
        } catch (IOException e) {
          log.error("Exception occurred during closing stream", e);
        }
      }
    }
  }

  public static byte[] readAsByteArray(File file) {
    FileInputStream fIn = null;
    ByteArrayOutputStream bos = null;
    try {
      fIn = new FileInputStream(file);
      bos = new ByteArrayOutputStream();
      byte[] buf = new byte[100000];
      int size;
      while ((size = fIn.read(buf)) != -1) {
        bos.write(buf, 0, size);
      }
      return bos.toByteArray();
    } catch (IOException e) {
      throw new RuntimeException(e);
    } finally {
      if (fIn != null) {
        try {
          fIn.close();
        } catch (IOException e) {
          log.error("Exception occurred during closing stream", e);
        }
      }
      if (bos != null) {
        try {
          bos.close();
        } catch (IOException e) {
          log.error("Exception occurred during closing stream", e);
        }
      }
    }
  }

  public static Object decompressObject(byte[] data) {
    ObjectInputStream in = null;
    try {
      in = new ObjectInputStream(new BufferedInputStream(new GZIPInputStream(new ByteArrayInputStream(data))));
      Object obj = in.readObject();
      return obj;
    } catch (Exception e) {
      throw new RuntimeException(e);
    } finally {
      if (in != null) {
        try {
          in.close();
        } catch (IOException e) {
          log.error("Exception occurred during closing stream", e);
        }
      }
    }
  }

  public static byte[] writeObject(Object obj) {
    ObjectOutputStream out;
    // Serialize to a byte array
    try {
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      out = new ObjectOutputStream(bos);
      out.writeObject(obj);
      out.close();

      // Get the bytes of the serialized object
      byte[] buf = bos.toByteArray();
      return buf;
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public static Object readObject(byte[] data) {
    try {
      ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data));
      Object obj = in.readObject();
      in.close();
      return obj;
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
}
